#include "core.h"
#include "Misc.h"
#include <stdio.h>

std::string CMisc::getIpPort( const std::string & ip, USHORT port )
{
	CHAR ip_port[ 60 ];
	sprintf( ip_port, "%s:%d", ip.c_str(), port );
	return ip_port;
}

void CMisc::getIpPortFromStr( std::string& ip, U16& port, std::string strIPPort)
{
	char strip[128] = {0};
	char ip_port[128] = {0};
	U32 s_port = 0;
	strncpy(ip_port, strIPPort.c_str(), 127);
	sscanf(ip_port, "%[^:]", &strip);
	sscanf(ip_port+strlen(strip)+1, "%d", &s_port);
	ip = strip;
	port = s_port;
}

U32 CMisc::ComputeLinearHash(const char* i_key)
{
	return(ComputeLinearHash(i_key, strlen(i_key)));
}

U32 CMisc::ComputeLinearHash(const void* i_key, int i_keyLen)
{
	register const unsigned char* k = (const unsigned char*)i_key;
	register U32 a, b, c;  /* the internal state */
	U32 len;               /* how many key bytes still need mixing */

	/* Set up the internal state */
	len = i_keyLen;
	a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
	c = 0;              /* always initialize this to 0 */

	/*---------------------------------------- handle most of the key */
	while (len >= 12)
	{
		a = a + (k[0] + ((U32)k[1] << 8) + ((U32)k[2] << 16) +
			((U32)k[3] << 24));
		b = b + (k[4] + ((U32)k[5] << 8) + ((U32)k[6] << 16) +
			((U32)k[7] << 24));
		c = c + (k[8] + ((U32)k[9] << 8) + ((U32)k[10] << 16) +
			((U32)k[11] << 24));
		MIX(a, b, c);
		k = k + 12;
		len = len - 12;
	}

	/*------------------------------------- handle the last 11 bytes */
	c = c + i_keyLen;

	/* all the case statements fall through */
	switch(len)
	{
	case 11:
		c = c + ((U32)k[10] << 24);
	case 10:
		c = c + ((U32)k[9] << 16);
	case 9:
		c = c + ((U32)k[8] << 8);

		/* the first byte of c is reserved for the length */
	case 8:
		b = b + ((U32)k[7] << 24);
	case 7:
		b = b + ((U32)k[6] << 16);
	case 6:
		b = b + ((U32)k[5] << 8);
	case 5:
		b = b + k[4];

	case 4:
		a = a + ((U32)k[3] << 24);
	case 3:
		a = a + ((U32)k[2] << 16);
	case 2:
		a = a + ((U32)k[1] << 8);
	case 1:
		a = a + k[0];
	}
	MIX(a, b, c);

	/*-------------------------------------------- report the result */
	return c;
}

BOOL CMisc::ToString(U8* pData, U32 dwLen, std::string& out)
{
	U8* pStr = new U8[dwLen*2+1];
	U32 destIndex = 0;
	for (U32 i = 0; i < dwLen; ++i)
	{
		U8 h = pData[i] >> 4;
		U8 l = pData[i] & 0xF;
		pStr[ destIndex++ ] = h < 0xA ? h + '0' : h + ( 'A' - 0xA );
		pStr[ destIndex++ ] = l < 0xA ? l + '0' : l + ( 'A' - 0xA );
	}
	pStr[ destIndex ] = 0;
	out = std::string((char*)pStr, dwLen*2);
	delete[] pStr;

	return TRUE;
}

BOOL HexToBinary( char & i_char )
{
	if ( i_char >= '0' && i_char <= '9' )
	{
		i_char -= '0';
	}
	else if ( i_char >= 'A' && i_char <= 'F' )
	{
		i_char -= 'A' - 0xa;
	}
	else if ( i_char >= 'a' && i_char <= 'f' )
	{
		i_char -= 'a' - 0xa;
	}
	else
	{
		return FALSE;
	}
	return TRUE;
}

BOOL CMisc::FromString(U8* pOut, U32& dwLen, std::string& in)
{
	if ( dwLen*2 >= in.size() )	{
		U32 destIndex = 0;
		U32 strLen = in.size();
		for (U32 i = 0; i < strLen; i+=2)
		{
			char h = in[i];
			char l = in[i+1];
			if (HexToBinary(h) && HexToBinary(l))	{
				pOut[destIndex++] = ( ( h << 4) | l);
			}
			else{
				return FALSE;
			}
		}
		dwLen = destIndex;
		return TRUE;
	}
	else{
		return FALSE;
	}
}
